package com.novunda.tool.qrcode;

/**
 * @author linfeng
 * @since 2016/11/10
 */
public class QRPolynomial {

    private int[] num;

    public QRPolynomial(int[] num, int shift) {

        if (num.length == 0) {
            throw new RuntimeException(num.length + "/" + shift);
        }

        int offset = 0;

        while (offset < num.length && num[offset] == 0) {
            offset++;
        }

        this.num = new int[num.length - offset + shift];
        System.arraycopy(num, offset, this.num, 0, num.length - offset);

    }

    public int get(int index) {
        return this.num[index];
    }

    public int getLength() {
        return this.num.length;
    }

    public QRPolynomial multiply(QRPolynomial polynomial) {
        int[] nums = new int[this.getLength() + polynomial.getLength() - 1];

        for (int i = 0; i < this.getLength(); i++) {
            for (int j = 0; j < polynomial.getLength(); j++) {
                nums[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(polynomial.get(j)));
            }
        }

        return new QRPolynomial(nums, 0);
    }

    public QRPolynomial mod(QRPolynomial polynomial) {
        if (this.getLength() - polynomial.getLength() < 0) {
            return this;
        }

        int ratio = QRMath.glog(this.get(0)) - QRMath.glog(polynomial.get(0));

        int[] num = new int[this.getLength()];

        for (int i = 0; i < this.getLength(); i++) {
            num[i] = this.get(i);
        }

        for (int i = 0; i < polynomial.getLength(); i++) {
            num[i] ^= QRMath.gexp(QRMath.glog(polynomial.get(i)) + ratio);
        }

        // recursive call
        return new QRPolynomial(num, 0).mod(polynomial);
    }

}